﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace FusionCharts.WebParts
{
    /// <summary>
    /// Represents an array of plots to graph
    /// </summary>
    public class Plots
    {
        /// <summary>
        /// xValues stored in an array that contains string
        /// </summary>
        private List<string> _xArray = new List<string>();
        /// <summary>
        /// yValues stored in an array of arrays of doubles
        /// _yArray[5][1] = 5th data point added, 2nd series
        /// </summary>
        private List<List<double>> _yArray = new List<List<double>>();
        /// <summary>
        /// Counts for yvalues - only used in group stats
        /// yctValues stored in an array of arrays of doubles
        /// _yctArray[5][1] = 5th data point added, 2nd series, #data elements
        /// </summary>
        private List<List<double>> _yctArray = new List<List<double>>();
        /// <summary>
        /// Number of y values per data point
        /// which is the same thing as number of series being plotted
        /// </summary>
        private int _nSeries;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="nseries">number of y values per data point</param>
        public Plots(int nseries)
        {
            _nSeries = nseries;
        }

        /// <summary>
        /// Adds a new plot 
        /// </summary>
        /// <param name="x">a string for xValue</param>
        /// <param name="yvalues">array of yValues</param>
        public void Add(string x, List<double> yvalues)
        {
            CheckPoint(x, yvalues, "Plots.Add");
            _xArray.Add(x);
            _yArray.Add(yvalues);
        }
        /// <summary>
        /// Adds a new plot 
        /// </summary>
        /// <param name="x">a string for xValue</param>
        /// <param name="yvalues">array of yValues</param>
        /// <param name="yctvalues">array of counts of yValues</param>
        public void AddWithCounts(string x, List<double> yvalues, List<double> yctvalues)
        {
            CheckPoint(x, yvalues, "Plots.Add");
            CheckPoint(x, yctvalues, "Plots.Add");
            _xArray.Add(x);
            _yArray.Add(yvalues);
            _yctArray.Add(yctvalues);
        }

        private void CheckPoint(string x, List<double> yvalues, string method)
        {
            if (yvalues.Count != _nSeries)
            {
                throw new Exception(string.Format(
                    "{0}: Wrong number data points ({1} should be {2}) for x value {3}"
                    , method
                    , yvalues.Count
                    , _nSeries
                    , IfNull(x, "<null>")
                    ));
            }
        }

        private static string IfNull(string x, string defval)
        {
            return x == null ? defval : x;
        }

        /// <summary>
        /// Gets an x value based on its position in the array
        /// </summary>
        /// <param name="pos"></param>
        /// <returns></returns>
        public string GetX(int pos)
        {
            return _xArray[pos].ToString();
        }

        /// <summary>
        /// Gets an y value based on its position in the array
        /// </summary>
        /// <param name="pos"></param>
        /// <returns></returns>
        public List<double> GetY(int pos)
        {
            string x = _xArray[pos];
            List<double> yvalues = _yArray[pos];
            CheckPoint(x, yvalues, "Plots.GetY");
            return yvalues;
        }

        /// <summary>
        /// Gets an yct value based on its position in the array
        /// </summary>
        /// <param name="pos"></param>
        /// <returns></returns>
        public List<double> GetYct(int pos)
        {
            string x = _xArray[pos];
            List<double> yctvalues = _yctArray[pos];
            CheckPoint(x, yctvalues, "Plots.GetYct");
            return yctvalues;
        }

        /// <summary>
        /// Returns true of the x value exists. Returns false if not.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public bool Contains(string x)
        {
            return _xArray.Contains(x);
        }

        /// <summary>
        /// Gets the index (position) of a element x
        /// </summary>
        /// <param name="x"></param>
        /// <returns>-1 if the elements is not present in the array</returns>
        public int XIndexOf(string x)
        {
            if (_xArray.Contains(x)) return _xArray.IndexOf(x);
            return -1;
        }

        /// <summary>
        /// Returns the number of elements in the array
        /// </summary>
        /// <returns></returns>
        public int Count()
        {
            return _xArray.Count;
        }

    }
}
